from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.uix.modalview import ModalView

from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.image import Image
from kivy.uix.textinput import TextInput
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import NumericProperty, ObjectProperty, StringProperty, AliasProperty, ListProperty, BooleanProperty
from kivy.event import EventDispatcher
from kivy.core.window import Window

from kivyext.spinbox import SpinBox
from kivyext.tablayout import TabLayout

import levinCommon

from kivy.lang import Builder
_kv_files_to_load = []
def load_kv_file(fname='', now=False,base=''):
    from os.path import join
    if fname:
        if not base:
            base = levinCommon.LEVINDIR
        Builder.load_file(join( base ,  fname) )

load_kv_file('kivyext/treegridview.kv')


class BottleWidget(EventDispatcher):
    bottle = ObjectProperty(None)

    def on_bottle(self, i, bottle):
        pass
    
class BBorderedWidget(Widget):

    border_frac = NumericProperty(0.05)
    border_color = ListProperty([0,0,0,1])
    ## _border_w1 = NumericProperty(0)
    ## _border_w2 = NumericProperty(0)
    ## _border_h1 = NumericProperty(0)
    ## _border_h2 = NumericProperty(0)
    ## _border_r1 = NumericProperty(0)
    ## _border_r2 = NumericProperty(0)
    ## _border_b1 = NumericProperty(0)
    ## _border_b2 = NumericProperty(0)

    def border_points(self, x,y,w,h, i=0):
        if i==0:
            self.set_bezier_border_points(x,y,w,h)
        return self._border_points[i]
    def set_bezier_border_points(self, x,y,w,h):
        f = self.border_frac
        w1 = min(max(w*f, 5), 15)
        w2 = w-w1
        h1 = min(max(h*f, 5), 15)
        h2 = h- h1
        t = y+h
        r = x+w

        self._border_points = [
            (x+w1,y, x,y, x,y+h1) , # 1st bezier
            (x,y+h1, x,y+h2) , # 1st line
            (x,y+h2, x,t, x+w1,t ) , # 2nd bezier
            (x+w1,t, x+w2,t ) , #
            (x+w2,t, r,t, r,y+h2 ) , #
            (r,y+h2, r,y+h1 ) , #
            (r,y+h1, r,y, x+w2,y ) , #
            (x+w2,y, x+w1,y ) , #
            ]

class LeVinSpinBox(SpinBox):
    pass

class CompactTextInput(TextInput):
    def set_focus(self, *l):
        self.focus = True

class CompactButton(Button):
    maxHeight = NumericProperty(32)
    pass

class CompactLabel(Label):
    maxHeight = NumericProperty(32)
    ## def on_height(self,*l):
    ##     print 'qqqqqqqqq CompactLabel height changed', self.text, self.height
    ## pass

class LeVinIconProvider(EventDispatcher):
    icon_src = StringProperty('')
    def _icon_size(self):
        return 0 if self.icon_src=='' else self.height -3*self.padding_y

    icon_size = AliasProperty(_icon_size, None,
                                  bind=('icon_src', 'height'))

    def hello(self):
        print ' LeVinButton ',self

class LeVinIconLabel(LeVinIconProvider, CompactLabel):
    pass

class LeVinCompactButton(LeVinIconProvider,CompactButton):
    pass


class LeVinTreeLabel(Label):
    bkg_color = ListProperty([0, 0, 0, 0])    
    
    ## def __init__(self, **kargs):
    ##     super(LeVinTreeLabel, self).__init__(**kargs)

    ##     self.shorten = True
    ## pass

    
class LeVinToggleButton(LeVinIconProvider,ToggleButton):
    pass
    
class LeVinButton(LeVinIconProvider,Button):
    pass

from kivy.clock import Clock , ClockEvent

class LeVinButtonBar(BoxLayout):

    def __init__(self,**kargs):
        self._trigger_resize_to_children =  Clock.create_trigger(self.resize_to_children, -1)
        super(LeVinButtonBar,self).__init__(**kargs)


    def resize_to_children(self,*l):
        #print '  ,,,,,,,,, resize_to_children ',self, [w.height for w in self.children]
        self.height = max(w.height for w in self.children)

    def tt(self,l):
        print
        print '!!',self, ' max height = ',[w.height for w in self.children] if self.children else None
        return l


class ModeButtonBar(LeVinButtonBar):
            
    def button_pressed(self, button):
        for b in self.children:
            if b != button :
                b.state = 'normal'
        button.state = 'down'


class ClickableImage(Image):
    pass



class LeVinTabButton(LeVinToggleButton):
    decoration_height = NumericProperty(10)
    pass

class LeVinTabLayout(TabLayout, BottleWidget):    

    buttonClass = ObjectProperty(LeVinTabButton)

    def __init__(self, **kargs):
        super(LeVinTabLayout, self).__init__(**kargs)
        commonEvents.bind(selectedBottle = setter(self,'bottle'))

    def on_bottle(self,i, bottle):
        c = self.contents.get( self.selected_content, None)
        if c:
            c.bottle = self.bottle

    def _change_tab (self, instance, value):
        self.content_obj.clear_widgets()
        w=self.contents.get (value, None)
        self.content_obj.add_widget (w)
        if w :
            w.bottle = self.bottle

## class LeVinAlertContent(BoxLayout):
##     validB = ObjectProperty(None)
##     cancelB = ObjectProperty(None)
##     validText = StringProperty("")
##     cancelText = StringProperty("")
##     alertText = StringProperty("")
    

class LeVinAlertModal(ModalView):
    validB = ObjectProperty(None)
    cancelB = ObjectProperty(None)
    content = ObjectProperty(None)
    validText = StringProperty(_("Ok"))
    cancelText = StringProperty(_("Cancel"))
    alertText = StringProperty("")

    #size_factor = NumericProperty(0.5)

    def __init__(self, addCancelB=True,addValidB=True,size_factor=0.5 ,
                 cancelCallBack = None,
                 validCallBack = None,
                 **k):
        k['size_hint'] = (size_factor,size_factor)
        k['attach_to'] = Window
        super(LeVinAlertModal,self).__init__(**k)

        def fullCallBack(cb):
            if cb is None:
                return self.dismiss
            def _fcb(*l):
                cb(*l)
                self.dismiss()
            return _fcb
        
        if addCancelB:
            self.cancelB.bind(on_release = fullCallBack(cancelCallBack) )
        else:
            self.remove_widget(self.cancelB)

        if addValidB:
            self.validB.bind(on_release = fullCallBack(validCallBack) )
        else:
            self.remove_widget(self.validB)

        if self.content:
            content.size_hint = (1,0.59)
            self.children[0].add_widget(content)
        else:
            self.children[0].add_widget(Label(text=self.alertText, size_hint = (1,0.59)))

class CameraCapture(ModalView):
    doneB = ObjectProperty(None)
    camera = ObjectProperty(None)
    doneCallBack = ObjectProperty(None)
    def done(self,*l):
        print 'CameraCapture',l
        self.dismiss()
        if self.doneCallBack:
            self.doneCallBack(self)

class LeVinAlert(Popup):
    _border_size = NumericProperty(2)
    validB = ObjectProperty(None)
    cancelB = ObjectProperty(None)
    validText = StringProperty(_("Ok"))
    cancelText = StringProperty(_("Cancel"))
    alertText = StringProperty("")

    size_factor = NumericProperty(0.5)
    def __init__(self, addCancelB=True,addValidB=True, **k):
        self.addCancelB = addCancelB
        self.addValidB = addValidB
        super(LeVinAlert,self).__init__(**k)
        self.size = (Window.width*self.size_factor,Window.height*self.size_factor)
        self.size_hint = (None,None)
        #size_hint: (None,None)
        if not self.content:
            self.content = Label(text=self.alertText)
        #size: (Window.width/2,Window.height/2)    
        
        #print 'alert ' ,self.size , self.size_hint
    def on_content(self,instance,value):
        super(LeVinAlert,self).on_content(instance,value)
        self.addAlertWid()
    def on__container(self,instance,value):
        super(LeVinAlert,self).on__container(instance,value)
        self.addAlertWid()

    def addAlertWid(self):
        if not self.cancelB and self.addCancelB:
            self.cancelB = LeVinButton(text = self.cancelText)
        if not self.validB and self.addValidB:
            self.validB  = LeVinButton(text = self.validText)

        if self._container:
            self._container.orientation = 'vertical'
            if self.addValidB: self._container.add_widget(self.validB)
            if self.addCancelB: self._container.add_widget(self.cancelB)

    def ask(self):
        self.res = False
        if self.cancelB:
            self.cancelB.bind(on_release = self.dismiss)
        if self.validB:
            def validAction(*l):
                self.res = True
                self.dismiss()
            self.validB.bind(on_release = validAction)
        self.open()
        return self.res

def setter(obj, att):
    def _set(o,v):
        setattr(obj,att,v)
    return _set

class LeVinCommon(EventDispatcher):

    desktopMode = BooleanProperty(False)
    selectedBottle = ObjectProperty(None)

    visibleWines   = NumericProperty(0)
    visibleBottles = NumericProperty(0)

    def __init__(self,**kargs):
        self.register_event_type('on_start_edit_bottle')
        self.register_event_type('on_start_edit_tasting')
        self.register_event_type('on_end_edit_bottle')
        self.register_event_type('on_end_edit_tasting')

        self.register_event_type('on_bottle_edited')
        self.register_event_type('on_tasting_edited')        

        self.register_event_type('on_delete_bottle')
        self.register_event_type('on_delete_tasting')

        self.register_event_type('on_cellar_mode')
        self.register_event_type('on_tastinglist_mode')

        self.register_event_type('on_wineselect_update')        

    def on_delete_bottle(self,*l):        
        pass
    def on_delete_tasting(self,*l):        
        pass

        
    def on_start_edit_bottle(self,*l):
        pass
    def on_start_edit_tasting(self,*l):
        pass
    def on_end_edit_bottle(self,*l):
        pass
    def on_end_edit_tasting(self,*l):
        pass

    def on_bottle_edited(self, *l):
        pass

    def on_tasting_edited(self, *l):
        pass

    def on_cellar_mode(self, *l):
        pass

    def on_tastinglist_mode(self, *l):
        pass

    def on_wineselect_update(self, *l):
        pass
    
commonEvents = LeVinCommon()

import kivyext.combobox
class LeVinCombo(kivyext.combobox.ComboBoxBase, LeVinButton):
    pass        

class LeVinIconCombo(kivyext.combobox.ComboBoxBase, LeVinButton):
    need_init = True
    icons = []
    def buildDropDown(self, *l):
        super(LeVinIconCombo,self).buildDropDown()
        if self.need_init:
            for v,ic in zip(self._widContent, self.icons):
                v.icon_src = ic
            self.icon_src = self.default_icon 
            #print ' ComboWithICons build list  ', ' __ ', self.popupwid.children
            self.need_init = False


class LeVinPopup(Popup):
    """Just to re-style Popup """
    pass

        
    

class LeVinComponents(object):
    wineWorld      = None
    wineWidgetTree = None
    mainScreen     = None

    tastingDisplay = None
    wineDisplay    = None
    areaDisplay    = None

    tastingListWidget    = None 

appComponents = LeVinComponents()

def switchScreen(s):
    appComponents.topWindow.current = s


from kivy.factory import Factory
for cls in [BBorderedWidget, CompactLabel, LeVinButtonBar, LeVinButton, LeVinToggleButton, CompactTextInput, LeVinAlert,LeVinAlertModal,
            LeVinTabLayout, LeVinTabButton, ClickableImage, LeVinPopup, LeVinCompactButton]:
    Factory.register(cls.__name__, cls=cls)



load_kv_file('guiCommon.kv')

## --------------------------------------
class VisibleWinesLabel(CompactLabel):
    """A label widget displaying the number of selected bottles & wines.
    Only one instance of this class expected.
    """
    pass
visibleWinesLabel = VisibleWinesLabel() # the instance.
_visibleWinesstr = _("%d bottles from %d wines")
def updateVisibleWinesLab(*l):
    """Update the VisibleWinesLabel text according to currently selected bottles """
    visibleWinesLabel.text = _visibleWinesstr%(commonEvents.visibleBottles,commonEvents.visibleWines)
commonEvents.bind( visibleWines = updateVisibleWinesLab, visibleBottles=updateVisibleWinesLab)
## --------------------------------------

